package org.polyforms.repository.intercept;

import javax.inject.Inject;
import javax.inject.Named;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.polyforms.repository.spi.EntityHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * {@link org.aopalliance.intercept.Interceptor} for attaching detached entity into {@link EntityManager} automatically.
 * 
 * @author Kuisong Tong
 * @since 1.0
 */
@Named
public final class AutoAttachableInterceptor implements MethodInterceptor {
    private static final Logger LOGGER = LoggerFactory.getLogger(AutoAttachableInterceptor.class);

    @PersistenceContext
    private EntityManager entityManager;

    private final EntityHelper entityHelper;

    /**
     * Create an instance with {@link EntityLifecycleResolver}.
     */
    @Inject
    public AutoAttachableInterceptor(final EntityHelper entityHelper) {
        this.entityHelper = entityHelper;
    }

    /**
     * {@inheritDoc}
     */
    public Object invoke(final MethodInvocation invocation) throws Throwable {
        final Object[] arguments = invocation.getArguments();
        for (int i = 0; i < arguments.length; i++) {
            final Object arg = arguments[i];
            if (arg != null && entityHelper.isEntity(arg.getClass()) && entityHelper.isDetached(arg)) {
                LOGGER.debug("auto attach {}", arg.toString());
                arguments[i] = entityManager.merge(arg);
            }
        }
        return invocation.proceed();
    }
}
